using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace DrawImageSample
{
    public struct Stroke
    {
        public Stroke(Color pColor, float pWidth)
        {
            this.Color = pColor;
            this.Width = pWidth;
            this.Points = new List<Point>();
            this.BoundingBox = new Rectangle();
        }

        public Color Color;
        public List<Point> Points;
        public float Width;
        public Rectangle BoundingBox;
    }

    public class Screen
    {
        private int mID;
        private List<Stroke> mStrokes;
        private ScreenThumbnail mThumbnail;
        private Bitmap mCachedImage;

        public Screen(int pID)
        {
            this.mID = pID;
            this.mStrokes = new List<Stroke>();

            Bitmap bitmap = new Bitmap(Variables.THUMBNAIL_WIDTH, Variables.THUMBNAIL_HEIGHT);
            this.mThumbnail = new ScreenThumbnail(bitmap, String.Format("Slide #{0}", this.mID + 1));
            this.mCachedImage = new Bitmap(Variables.CANVAS_WIDTH, Variables.CANVAS_HEIGHT);
        }

        public Screen(Screen pScreen, int pID)
        {
            this.mID = pID;
            this.mStrokes = new List<Stroke>();

            Bitmap bitmap = new Bitmap(Variables.THUMBNAIL_WIDTH, Variables.THUMBNAIL_HEIGHT);
            this.mThumbnail = new ScreenThumbnail(bitmap, String.Format("Slide #{0}", this.mID + 1));
            this.mCachedImage = pScreen.mCachedImage.Clone() as Bitmap;

            foreach (Stroke stroke in pScreen.mStrokes)
            {
                this.mStrokes.Add(stroke);
            }
        }

        public int ID
        {
            get
            {
                return this.mID;
            }
            set
            {
                this.mID = value;
            }
        }

        public ScreenThumbnail Thumbnail
        {
            get
            {
                return this.mThumbnail;
            }
        }

        public void Select()
        {
            this.mThumbnail.SelectThumbnail();
        }

        public void AddStroke(Stroke pStroke)
        {
            if (pStroke.Points.Count > 0)
            {
                this.mStrokes.Add(pStroke);
            }
        }

        public void Clear()
        {
            // clear strokes
            this.mStrokes.Clear();
        }

        public void Draw(Graphics pGraphics, float pScale)
        {
            float delta = 0.001f;
            foreach (Stroke stroke in this.mStrokes)
            {
                //if (pGraphics.ClipBounds.IntersectsWith(stroke.BoundingBox))
                //{
                    // get the pen
                    Pen pen = Resources.GetPen(stroke.Color, stroke.Width * pScale);

                    // draw the strokes lines in scale
                    Point lastPoint = stroke.Points[0];
                    foreach (Point point in stroke.Points)
                    {
                        pGraphics.DrawLine(pen, lastPoint.X * pScale, lastPoint.Y * pScale, point.X * pScale + delta, point.Y * pScale + delta);
                        lastPoint = point;
                    }
                //}
            }
        }

        public void Save()
        {
            // save image ID (~temp\ImageList.tmp\0001.JPG)
            Random rnd = new Random();
            string path = String.Format("{0}\\ImageList.tmp", Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            // now save this screen
            using (Bitmap bitmap = new Bitmap(Variables.THUMBNAIL_WIDTH, Variables.THUMBNAIL_HEIGHT))
            {
                this.Draw(Resources.GetGraphics(Graphics.FromImage(bitmap)), ((float)Variables.THUMBNAIL_WIDTH / (float)Variables.CANVAS_WIDTH));
                bitmap.Save(String.Format("{0}\\{1:0000}.jpg", path, this.mID));
            }
        }

        public void ReadFromFile(TextReader tr)
        {
            Color color;
            float width;
            int i, j, x, y, numPoints;
            int numStrokes = Convert.ToInt32(tr.ReadLine());
            Stroke stroke;
            for (i = 0; i < numStrokes; i++)
            {
                color = Color.FromArgb(Convert.ToInt32(tr.ReadLine()));
                width = Convert.ToSingle(tr.ReadLine());
                stroke = new Stroke(color, width);
                numPoints = Convert.ToInt32(tr.ReadLine());
                for(j = 0; j < numPoints; j++)
                {
                    x = Convert.ToInt32(tr.ReadLine());
                    y = Convert.ToInt32(tr.ReadLine());
                    stroke.Points.Add(new Point(x, y));
                }
                this.mStrokes.Add(stroke);
            }
            tr.ReadLine();
        }

        public void WriteToFile(TextWriter tw)
        {
            tw.WriteLine(this.mStrokes.Count);
            foreach (Stroke stroke in this.mStrokes)
            {
                tw.WriteLine(stroke.Color.ToArgb());
                tw.WriteLine(stroke.Width);
                tw.WriteLine(stroke.Points.Count);
                foreach (Point point in stroke.Points)
                {
                    tw.WriteLine(point.X);
                    tw.WriteLine(point.Y);
                }
            }
            tw.WriteLine();
        }
    }
}
